package org.convallaria.framework.security.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.convallaria.framework.security.annotation.Anonymous;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * 匿名访问切面
 * 处理@Anonymous注解标记的方法
 * 
 * 注意：此切面主要用于代码层面的声明和日志记录，
 * 实际的匿名访问控制主要由Spring Security白名单配置处理。
 * 
 * @author convallaria
 * @since 1.0.0
 */
@Slf4j
@Aspect
@Component
@Order(1) // 确保在权限切面之前执行
public class AnonymousAspect {

    /**
     * 处理@Anonymous注解标记的方法
     * 
     * 注意：由于Spring Security白名单已经在过滤器层面处理了匿名访问，
     * 此切面主要用于：
     * 1. 代码层面的声明和文档化
     * 2. 日志记录和监控
     * 3. 作为白名单配置的补充
     * 
     * @param joinPoint 连接点
     * @param anonymous 匿名访问注解
     * @return 方法执行结果
     * @throws Throwable 异常
     */
    @Around("@annotation(anonymous)")
    public Object handleAnonymous(ProceedingJoinPoint joinPoint, Anonymous anonymous) throws Throwable {
        String methodName = joinPoint.getSignature().getName();
        String className = joinPoint.getSignature().getDeclaringType().getSimpleName();
        
        log.debug("执行匿名访问方法: {}.{}", className, methodName);
        
        // 记录匿名访问日志（用于监控和审计）
        logAnonymousAccess(className, methodName, joinPoint.getArgs());
        
        // 直接执行方法
        return joinPoint.proceed();
    }

    /**
     * 处理类级别的@Anonymous注解
     * 
     * @param joinPoint 连接点
     * @param anonymous 匿名访问注解
     * @return 方法执行结果
     * @throws Throwable 异常
     */
    @Around("@within(anonymous) && !@annotation(org.convallaria.framework.security.annotation.Anonymous)")
    public Object handleAnonymousClass(ProceedingJoinPoint joinPoint, Anonymous anonymous) throws Throwable {
        String methodName = joinPoint.getSignature().getName();
        String className = joinPoint.getSignature().getDeclaringType().getSimpleName();
        
        log.debug("执行匿名访问类方法: {}.{}", className, methodName);
        
        // 记录匿名访问日志
        logAnonymousAccess(className, methodName, joinPoint.getArgs());
        
        // 直接执行方法
        return joinPoint.proceed();
    }

    /**
     * 记录匿名访问日志
     * 
     * @param className 类名
     * @param methodName 方法名
     * @param args 方法参数
     */
    private void logAnonymousAccess(String className, String methodName, Object[] args) {
        // 这里可以添加更详细的日志记录逻辑
        // 例如：记录到专门的匿名访问日志表
        log.info("匿名访问: {}.{}", className, methodName);
        
        // 可以在这里添加监控指标
        // 例如：增加匿名访问计数器
    }
}
